Parser.php
<?php
namespace Breg;
class Parser {
// protected $regex;
protected $patterns = [
'function'=> '/\:\:([a-zA-Z0-9\_]*)\((.*)\)/',
'comment'=>'/(?:^|\s)#[^\n]*$/m',
'pad'=> '/(^\s*|\s*$)/m',
'esc_trail_slash'=>'/(^|[^\\\\])((?:\\\\\\\\)*)(\\\\)$/m',
'replace_esc_trail_slash'=>'$1$2\\ ',
];
/**
* parse a regex string into an array
*
*/
public function parse($regex){
$parsed = ['source_reg'=>$regex, 'functions'=>[], 'clean_reg'=>null];
$reg = $regex;
$cleanReg = $reg;
$cleanReg = $this->removeComments($cleanReg);
$cleanReg = $this->removePad($cleanReg);
$cleanReg = $this->addEscapedTrailingSpace($cleanReg);
$cleanReg = $this->implodeLines($cleanReg);
$parsed['clean_reg'] = $cleanReg;
$split = explode("\n",$reg);
$lines = array_map([$this,'cleanLine'], $split);
$functions = [];
$i = 0;
do {
$line = $lines[$i];
$func = $this->parseRegFunc($line);
if ($func==false)continue;
$parsed['functions'][] = $func;
} while (count($lines)>++$i);
// echo "\n\n";
// var_dump($parsed);
// echo "\n\n";
// exit;
return $parsed;
}
// public function replace($function, $string){
// $this->regex = str_replace($function->declaration, $string,$this->regex);
// }
//
protected function removeComments($reg){
$reg = preg_replace($this->patterns['comment'],'',$reg);
return $reg;
}
protected function removePad($reg){
$reg = preg_replace($this->patterns['pad'],'',$reg);
return $reg;
}
protected function addEscapedTrailingSpace($reg){
$reg = preg_replace($this->patterns['esc_trail_slash'], $this->patterns['replace_esc_trail_slash'], $reg);
return $reg;
}
protected function implodeLines($reg){
$arrayOfLines = explode("\n",
str_replace(["\r\n","\n\r","\r"],"\n",$reg)
);
$reg = implode('',$arrayOfLines);
return $reg;
}
/**
* Each comment must start with ` #` (space hash). Everything following in that line is comment and will be removed from output
* If your pattern uses ` #`, escape it like ` \#`
*
* @export(Syntax.Comments)
*/
protected function cleanLine($regLine){
// $
$pos = strpos($regLine,' ## ');
if ($pos!==false)$regLine = substr($regLine,0,$pos);
$regLine = trim($regLine);
return trim($regLine);
}
/**
* ```
* ::functionName(arg1 ;; arg2 ;; arg3) ## Comments if you want
* ```
* - The function must be the only thing on the line. Comments allowed.
* - Args must **not** be quoted. Every arg will be trimmed (surrounding whitespace is removed).
* - Args are separated by ' ;; ' (space semicolon semicolon space)
*
*
* @export(Syntax.Functions)
*/
protected function parseRegFunc($line){
// $funcReg = '/^\:\:([a-zA-Z0-9]*)\((.*)\)$/';
$funcReg = '/\:\:([a-zA-Z0-9]*)\((.*)\)/';
// $refListReg = '/\{\{([a-zA-Z\.0-9]+)\}\}/';
$matches = [];
$match = preg_match($this->patterns['function'],$line,$matches);
if (!$match) return false;
$specialCharsReg = '\.\-\_';
/**
* Functions can accept a refs list as an argument. Each ref is closed in double moustaches `{{refname}}`
* ```
* ## Combine selected refs with the bar (|) separator
* ::combine( {{ref1}}{{ref2}}{{ref3}} ;; |)
* ```
* Each ref name can be composed of `a-z`, `A-Z`, `0-9`, and/or special chars: `. - _`
*
* @export(Syntax.Refs)
*/
$getRefs = '/\{\{([a-zA-Z'.$specialCharsReg.'0-9]+)\}\}/';
$isRefsArg = '/^(\{\{([a-zA-Z'.$specialCharsReg.'0-9]+)\}\})+$/';
$funcName = $matches[1];
$argsList = explode(' ;; ',$matches[2]);
$finalArgList = [];
$func = ['definition'=>$matches[0],'name'=>$funcName,'args'=>[], 'argString'=>$matches[2]];
while ($arg = current($argsList)){
next($argsList);
$arg = trim($arg);
if (preg_match($isRefsArg,$arg)){
// echo "IS REF ARG: ".$arg."\n\n";
$refs = [];
preg_match_all($getRefs,$arg,$refs);
// $func['items'][] = $refs[1];
// var_dump($refs);
// $arg = $this->namespace.'.'.$refs[1][0];
$arg = $refs[1];
}
$func['args'][] = $arg;
}
return $func;
}
}